package cc.wanforme.st.server.base.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

import cc.wanforme.st.server.base.constant.CacheKeys;
import cc.wanforme.st.server.base.entity.Permission;
import cc.wanforme.st.server.base.entity.Role;
import cc.wanforme.st.server.base.entity.RolePermission;
import cc.wanforme.st.server.base.mapper.RolePermissionMapper;
import cc.wanforme.st.server.base.service.IPermissionService;
import cc.wanforme.st.server.base.service.IRolePermissionService;
import cc.wanforme.st.server.base.service.IRoleService;
import cc.wanforme.st.server.base.service.cache.RoleCacheService;
import cc.wanforme.st.server.util.AssertCheck;
import cc.wanforme.st.server.vo.base.RolePermissionVo;


/**
 * @author wanne
 * 2020年10月23日
 */
@Service
public class RolePermissionServiceImpl extends ServiceImpl<RolePermissionMapper, RolePermission>
	implements IRolePermissionService{
	
	@Autowired
	private IRoleService roleService;
	@Autowired
	private IPermissionService permissionService;
	@Autowired
	private RoleCacheService roleCacheService;
	
	@Override
	@Cacheable(cacheNames = CacheKeys.ROLE_PERMISSION)
	public List<RolePermission> selectPermissions(String role) {
		return this.baseMapper.selectAuth(role);
	}

	/** 清除某个角色的缓存， 不要在实现类内部调用 */
	@Override
	public void clearCache(String role) {
		roleCacheService.clearCache(role);
	}
	
	@Override
	public RolePermission saveVo(RolePermission vo) {
		AssertCheck.nonNull(vo.getRole(), "角色不能为空");
		AssertCheck.nonNull(vo.getPermission(), "权限不能为空");
		
		Role role = roleService.getById(vo.getRole());
		AssertCheck.nonNull(role, "角色不存在");
		
		Permission permission = permissionService.getByPermissionCode(vo.getPermission());
		AssertCheck.nonNull(permission, "权限不存在");
		
		this.save(vo);
		return vo;
	}

	@Override
	public void updateVo(RolePermission vo) {
		AssertCheck.nonNull(vo.getId(), "未知操作");
		AssertCheck.nonNull(vo.getRole(), "角色不能为空");
		AssertCheck.nonNull(vo.getPermission(), "权限不能为空");
		
		Role role = roleService.getById(vo.getRole());
		AssertCheck.nonNull(role, "角色不存在");
		
		Permission permission = permissionService.getByPermissionCode(vo.getPermission());
		AssertCheck.nonNull(permission, "权限不存在");
		
		this.updateById(vo);
	}

	@Override
	public void deleteVo(Long id) {
		this.baseMapper.deleteById(id);
	}

	@Override
	public void deleteVo(String roleCode, String permission) {
		this.baseMapper.deleteByRoleAndPermission(roleCode, permission);
	}

	@Override
	public void deleteAllByRole(String role) {
		this.baseMapper.deleteAllByRole(role);
	}

	@Override
	public void deleteAllPermission(String permission) {
		this.baseMapper.deleteAllPermission(permission);
	}
	
	@Override
	public PageInfo<RolePermission> listRolePermissions(int page, int pageSize, String roleLike) {
		PageHelper.startPage(page, pageSize);
		List<RolePermission> list = this.baseMapper.listRolePermissions(roleLike);
		return new PageInfo<RolePermission>(list);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void updateRoleAllPermissions(RolePermissionVo vo) {
		AssertCheck.nonNull(vo.getRole(), "角色为空");
		AssertCheck.nonNull(vo.getPermissions(), "没有设置权限");
		
		List<String> permissions = vo.getPermissions();
		
		List<RolePermission> oldAll = this.selectPermissions(vo.getRole());
		if(oldAll == null) {
			oldAll = new ArrayList<>(0);
		}
		
		// 删除
		List<RolePermission> delList = oldAll.stream()
				.filter(e -> !permissions.contains(e.getPermission()))
				.collect(Collectors.toList());
		// 旧所有
		List<String> oldListAll = oldAll.stream()
				.map(RolePermission::getPermission)
				.collect(Collectors.toList());
		// 新增
		List<RolePermission> saveList = (new ArrayList<>(permissions)).stream()
					.filter(e2 -> !oldListAll.contains(e2))
					.map(e3 -> {
						RolePermission newPo = new RolePermission();
						newPo.setRole(vo.getRole());
						newPo.setPermission(e3);
						return newPo;
					}).collect(Collectors.toList());
		
		for (RolePermission del : delList) {
			this.baseMapper.deleteById(del);
		}
		this.saveBatch(saveList, 100);
		
		roleCacheService.clearCache(vo.getRole());
	}


}
